#include<vector>
#include<string>
#include<stdint.h>
#include<cstring>
#include<cassert>

class Buffer
{
private:
    std::vector<char> _buf;                 //空间
    uint64_t _read_offset;                  //读偏移
    uint64_t _write_offset;                 //写偏移
private:                                    //私有接口，不对外，用于内部功能的实现
    char* ReadPosition()                    //获取读起始位置
    {return &_buf[_read_offset];}
    uint64_t FrontWriteSize()const          //获取读偏移之前的空闲空间
    {return _read_offset;}
    uint64_t BehindWriteSize()const         //获取写偏移之后的空闲空间
    {return _buf.size()-_write_offset;}
    uint64_t TotalWriteSize()const          //获取总的可写空间
    {return FrontWriteSize()+BehindWriteSize();}
    char* WritePosition()                   //写入的起始位置
    {return &_buf[_write_offset];}
    bool EnsureWriteSize(size_t len)        //用来移动数据以及扩容等，保证写空间足够
    {
        if(BehindWriteSize()>=len) return true;
        if(TotalWriteSize()>=len)
        {
            //将可读数据往前挪动
            memcpy(&_buf[0],ReadPosition(),ReadSize()); 
            _read_offset =0;
            _write_offset = ReadSize();  
            return true;
        }
        //空间不够需要扩容
        _buf.resize(_write_offset+len);
        return true;
    } 
    bool MoveReadOffset(size_t len)         //移动读偏移
    {
        assert(len<=ReadSize());
        _read_offset += len;
        return true;
    }
    bool MoveWriteOffset(size_t len)        //游动写偏移
    {
        assert(len<=BehindWriteSize());
        _write_offset += len;
        return true;
    }
public:                                     //对外提供的功能接口   
#define INIT_SIZE 1024
    Buffer()                                //构造函数 
    :_buf(1024),_read_offset(0),_write_offset(0){}     
    uint64_t ReadSize() const               //获取可读数据大小
    {return _write_offset-_read_offset;}
    bool Read(char*out,size_t len)          //读取数据，不移动读偏移
    {
        assert(len<=ReadSize());
        memcpy(out,ReadPosition(),len);
        return true;
    }
    bool ReadAndPop(char*out,size_t len)    //读取数据并移动读偏移 
    {
        Read(out,len);
        MoveReadOffset(len);
        return true;
    }                    
    bool Write(const char*in,size_t len)          //写入数据，不移动写偏移
    {
        EnsureWriteSize(len);
        memcpy(WritePosition(),in,len);
        return true;
    }
    bool WriteAndPush(const char*in,size_t len)   //写入数据并移动写偏移
    {
        Write(in,len);
        MoveWriteOffset(len);
        return true;
    }
    std::string ReadAsString(size_t len)    //读取数据，返回string,不移动读偏移
    {
        assert(len<=ReadSize());
        std::string ret;
        ret.resize(len);
        memcpy(&ret[0],ReadPosition(),len);
        return ret;
    }
    std::string ReadAsStringAndPop(size_t len) //读取数据，返回string,并移动读偏移
    {
        std::string ret = ReadAsString(len);
        MoveReadOffset(len);
        return ret;
    }
    bool WriteString(const std::string& in) //写入string的数据不移动写偏移
    {
        return Write(WritePosition(),in.size());
    }
    bool WriteStringAndPush(const std::string&in)   //写入string的数据并移动写偏移
    {
        return WriteAndPush(in.c_str(),in.size());
    }
#define MAX_LINE_SIZE 8092   //我们规定一行不能超过8092，因为一般来说不可能出现怎么长的一行内容，出现了，就说明可能出问题了
    std::string GetLine()                   //获取一行数据
    {
        int i = 0;
        char* start = ReadPosition();
        for(;i<ReadSize()&&i<MAX_LINE_SIZE;++i)
        {
            if(start[i]=='\n') break;
        }
        std::string ret;
        if(i!=ReadSize()&&i!=MAX_LINE_SIZE) ret = std::string(start,i+1);  //注意要提取 i+1 个字节，而不是i个
        return ret;
    }
    std::string GetLineAndPop()             //获取一行数据并移动读偏移
    {
        std::string  ret = GetLine();
        //如果没有获取到一行，ret.size() 就是 0
        MoveReadOffset(ret.size());
        return ret; 
    }
    void Clear()                            //清除缓冲区数据
    {_buf.clear();}
};

